package com.sc;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

/**
 * @author sc
 * Created on  2017/12/15
 * 单线程Reactor模式
 */
public class NioSingleServer {
    public static int PORT = 8080;
    private ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
    public static void main(String[] args) throws IOException {
      new NioSingleServer().go(args);
    }

    public void go(String[] arg) throws IOException {
        int port = PORT;
        System.out.println("Listening port on "+port);
        //打开一个通道
        ServerSocketChannel ssc  = ServerSocketChannel.open();
        //绑定一个socket
        ServerSocket serverSocket = ssc.socket();
        //创建一个selector
        Selector selector = Selector.open();
        //设置socket监控的端口
        serverSocket.bind(new InetSocketAddress(port));
        ssc.configureBlocking(false);
        ssc.register(selector, SelectionKey.OP_ACCEPT);
        while(true){
            int n = selector.select();
            if(n==0){
                continue;
            }
            Iterator<SelectionKey> it = selector.selectedKeys().iterator();
            while(it.hasNext()){
                SelectionKey key = it.next();
                //判断是否有连接到来
                if(key.isAcceptable()){
                    ServerSocketChannel server = (ServerSocketChannel) key.channel();
                    SocketChannel socketChannel = server.accept();
                    socketChannel.configureBlocking(false);
                    socketChannel.register(key.selector(),SelectionKey.OP_ACCEPT);
                    sayHello(socketChannel);
                }
                if(key.isReadable()){
                    readDataFromSocket(key);
                }
            }
        }
    }

    private void sayHello(SocketChannel socketChannel) throws IOException {
        byteBuffer.clear();
        byteBuffer.put("Hi ====".getBytes());
        byteBuffer.flip();
        socketChannel.write(byteBuffer);
    }

    private void readDataFromSocket(SelectionKey key) throws IOException {
        SocketChannel socketChannel = (SocketChannel) key.channel();
        int count;
        byteBuffer.clear();
        while ((count = socketChannel.read(byteBuffer))>0){
            byteBuffer.flip();
            while(byteBuffer.hasRemaining()){
                socketChannel.write(byteBuffer);
            }
            byteBuffer.clear();
        }
        if(count<0){
            socketChannel.close();
        }
    }
}
